import * as THREE from "three";
import type { Ref } from "vue";

export interface Property {
  key: string;
  value: string;
}

export interface SelectableObject {
  id: string;
  type: "point" | "shield" | "model";
  name: string;
  object3D?: THREE.Object3D;
  properties: Property[];
}

export interface MonitoringPoint {
  point_id: number;
  point_name: string;
  point_type: string;
  alert_level: "ERROR" | "WARNING" | "ATTENTION" | null;
  x: number;
  y: number;
  z: number;
}

export interface ShieldArea {
  id: number;
  name: string;
  is_active: boolean;
  is_visible: boolean;
  coordinates?: any;
  geom?: any;
}

export class SelectionManager {
  private scene: THREE.Scene | null = null;
  private camera: THREE.PerspectiveCamera | null = null;
  private controls: any = null;
  private renderer: THREE.WebGLRenderer | null = null;

  // Reactive properties
  public selectedObject: Ref<SelectableObject | null>;
  public selectedProperties: Ref<Property[]>;
  public isSelecting: Ref<boolean>;

  // 外部数据引用
  private monitoringPoints: Ref<MonitoringPoint[]>;
  private shieldAreas: Ref<ShieldArea[]>;
  private model: THREE.Group | null = null;
  private modelCenter: THREE.Vector3 = new THREE.Vector3();
  private scaleFactor: number = 1;

  // 坐标偏移常量
  private readonly COORDINATE_OFFSET = {
    x: 2372256.14,
    y: 773022,
    z: 0,
  };

  constructor(
    selectedObject: Ref<SelectableObject | null>,
    selectedProperties: Ref<Property[]>,
    isSelecting: Ref<boolean>,
    monitoringPoints: Ref<MonitoringPoint[]>,
    shieldAreas: Ref<ShieldArea[]>
  ) {
    this.selectedObject = selectedObject;
    this.selectedProperties = selectedProperties;
    this.isSelecting = isSelecting;
    this.monitoringPoints = monitoringPoints;
    this.shieldAreas = shieldAreas;
  }

  // 初始化选择管理器
  public initialize(
    scene: THREE.Scene,
    camera: THREE.PerspectiveCamera,
    controls: any,
    renderer: THREE.WebGLRenderer,
    model: THREE.Group | null,
    modelCenter: THREE.Vector3,
    scaleFactor: number
  ): void {
    this.scene = scene;
    this.camera = camera;
    this.controls = controls;
    this.renderer = renderer;
    this.model = model;
    this.modelCenter = modelCenter;
    this.scaleFactor = scaleFactor;

    this.initSelection();
  }

  // 在 SelectionManager 类中添加右键支持
  private initSelection(): void {
    if (!this.renderer || !this.scene) return;

    const canvasElement = this.renderer.domElement;
    if (!canvasElement) return;

    // 添加左键点击事件监听
    canvasElement.addEventListener("click", this.handleCanvasClick.bind(this));

    // 添加右键点击事件监听
    canvasElement.addEventListener(
      "contextmenu",
      this.handleCanvasRightClick.bind(this)
    );

    console.log("选择功能已初始化（支持左键和右键）");
  }

  // 处理画布点击事件
  private handleCanvasClick(event: MouseEvent): void {
    if (!this.isSelecting.value || !this.camera || !this.scene) return;

    const canvasElement = this.renderer?.domElement;
    if (!canvasElement) return;

    const mouse = new THREE.Vector2();
    const rect = canvasElement.getBoundingClientRect();

    // 计算标准化设备坐标
    mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
    mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;

    // 执行射线检测
    this.performRaycast(mouse);
  }

  // 执行射线检测
  private performRaycast(mouse: THREE.Vector2): void {
    if (!this.camera || !this.scene) return;

    const raycaster = new THREE.Raycaster();
    raycaster.setFromCamera(mouse, this.camera);

    // 收集所有可选择的物体
    const selectableObjects: THREE.Object3D[] = [];

    this.scene.traverse((child) => {
      if (this.isSelectable(child)) {
        selectableObjects.push(child);
      }
    });

    const intersects = raycaster.intersectObjects(selectableObjects);

    if (intersects.length > 0) {
      const firstIntersect = intersects[0];
      this.handleObjectSelect(firstIntersect.object);
    } else {
      // 没有选中任何物体，清除选择
      this.clearSelection();
    }
  }

  // 判断物体是否可选择
  private isSelectable(object: THREE.Object3D): boolean {
    // 监测点
    if (object.name.startsWith("point_")) return true;
    // 屏蔽区域
    if (object.name.startsWith("shield_area_")) return true;
    // 模型
    if (object.name === "output0") return true;

    return false;
  }

  // 处理物体选择
  private handleObjectSelect(object: THREE.Object3D): void {
    // 清除之前的选择高亮
    this.clearSelectionHighlight();

    let selectableObject: SelectableObject | null = null;

    // 根据物体类型创建选择对象
    if (object.name.startsWith("point_")) {
      selectableObject = this.createPointSelection(object);
    } else if (object.name.startsWith("shield_area_")) {
      selectableObject = this.createShieldAreaSelection(object);
    } else if (object.name === "output0") {
      selectableObject = this.createModelSelection(object);
    }

    if (selectableObject) {
      this.selectedObject.value = selectableObject;
      this.selectedProperties.value = selectableObject.properties;

      // 高亮显示选中的物体
      this.highlightSelectedObject(object);

      console.log("选中对象:", selectableObject);
    }
  }

  // 创建监测点选择对象
  private createPointSelection(object: THREE.Object3D): SelectableObject {
    const pointName = object.name.replace("point_", "");
    const point = this.monitoringPoints.value.find(
      (p) => p.point_name === pointName
    );

    const properties: Property[] = [
      { key: "名称", value: pointName },
      { key: "类型", value: "监测点" },
      { key: "X坐标", value: point?.x?.toString() || "N/A" },
      { key: "Y坐标", value: point?.y?.toString() || "N/A" },
      { key: "Z坐标", value: point?.z?.toString() || "N/A" },
      { key: "告警级别", value: point?.alert_level || "N/A" },
      { key: "点ID", value: point?.point_id?.toString() || "N/A" },
    ];

    return {
      id: `point_${pointName}`,
      type: "point",
      name: pointName,
      object3D: object,
      properties,
    };
  }

  // 创建屏蔽区域选择对象
  private createShieldAreaSelection(object: THREE.Object3D): SelectableObject {
    const shieldAreaId = object.name.replace("shield_area_", "");
    const shieldArea = this.shieldAreas.value.find(
      (area) => area.id.toString() === shieldAreaId
    );

    const properties: Property[] = [
      { key: "名称", value: shieldArea?.name || "未知屏蔽区域" },
      { key: "类型", value: "屏蔽区域" },
      { key: "区域ID", value: shieldAreaId },
      { key: "状态", value: shieldArea?.is_active ? "激活" : "未激活" },
      { key: "可见性", value: shieldArea?.is_visible ? "可见" : "隐藏" },
    ];

    return {
      id: `shield_${shieldAreaId}`,
      type: "shield",
      name: shieldArea?.name || "屏蔽区域",
      object3D: object,
      properties,
    };
  }

  // 创建模型选择对象
  private createModelSelection(
    object: THREE.Object3D
  ): SelectableObject | null {
    if (!this.model) return null;

    const box = new THREE.Box3().setFromObject(this.model);
    const size = box.getSize(new THREE.Vector3());

    const properties: Property[] = [
      { key: "名称", value: "采场模型" },
      { key: "类型", value: "三维模型" },
      { key: "中心X", value: this.modelCenter.x.toFixed(2) },
      { key: "中心Y", value: this.modelCenter.y.toFixed(2) },
      { key: "中心Z", value: this.modelCenter.z.toFixed(2) },
      { key: "宽度", value: size.x.toFixed(2) },
      { key: "高度", value: size.y.toFixed(2) },
      { key: "深度", value: size.z.toFixed(2) },
    ];

    return {
      id: "model_output0",
      type: "model",
      name: "采场模型",
      object3D: object,
      properties,
    };
  }

  // 高亮显示选中的物体
  private highlightSelectedObject(object: THREE.Object3D): void {
    if (object instanceof THREE.Mesh) {
      // 保存原始材质
      object.userData.originalMaterial = object.material;

      // 创建高亮材质
      const highlightMaterial = new THREE.MeshBasicMaterial({
        color: 0x00ff00,
        transparent: true,
        opacity: 0.8,
        wireframe: false,
      });

      object.material = highlightMaterial;
    }
  }

  // 清除选择高亮
  public clearSelectionHighlight(): void {
    if (!this.scene) return;

    this.scene.traverse((child) => {
      if (child instanceof THREE.Mesh && child.userData.originalMaterial) {
        child.material = child.userData.originalMaterial;
        delete child.userData.originalMaterial;
      }
    });
  }

  // 清除选择
  public clearSelection(): void {
    this.clearSelectionHighlight();
    this.selectedObject.value = null;
    this.selectedProperties.value = [];
  }

  // 切换选择模式
  public toggleSelectionMode(): void {
    this.isSelecting.value = !this.isSelecting.value;
  }

  // 统一的定位方法
  public focusOnSelectedObject(): void {
    if (
      !this.selectedObject.value ||
      !this.selectedObject.value.object3D ||
      !this.camera ||
      !this.controls
    )
      return;

    const object = this.selectedObject.value.object3D;
    this.focusOnObject(object);
  }
  // 优化的定位方法
  public focusOnObject(object: THREE.Object3D): void {
    if (!this.camera || !this.controls) return;

    const box = new THREE.Box3().setFromObject(object);
    const center = box.getCenter(new THREE.Vector3());
    const size = box.getSize(new THREE.Vector3());
    const maxDim = Math.max(size.x, size.y, size.z);

    // 根据对象类型使用不同的距离策略 - 减小距离让对象看起来更大
    let distance: number;

    if (object.name.startsWith("point_")) {
      // 监测点：使用更小的固定距离，让点看起来更大
      distance = 200; // 从800减小到200
    } else if (object.name.startsWith("shield_area_")) {
      // 屏蔽区域：基于区域大小，使用更小的倍数
      distance = Math.max(maxDim * 1.2, 300); // 从2倍减小到1.2倍
    } else if (object.name === "output0") {
      // 模型：基于模型大小，使用更小的倍数
      distance = Math.max(maxDim * 1.0, 800); // 从1.5倍减小到1.0倍
    } else {
      // 默认策略
      distance = Math.max(maxDim * 1.0, 200); // 减小倍数
    }

    // 确保最小距离（进一步减小）
    distance = Math.max(distance, 100);

    const direction = new THREE.Vector3();
    this.camera.getWorldDirection(direction);

    this.camera.position.copy(center);
    this.camera.position.addScaledVector(direction, -distance);

    this.controls.target.copy(center);
    this.controls.update();

    console.log(
      `定位对象: ${object.name}, 尺寸: ${maxDim.toFixed(
        2
      )}, 距离: ${distance.toFixed(2)}`
    );
  }

  // 优化点名称定位的距离
  public focusOnPoint(pointName: string): boolean {
    if (!this.camera || !this.controls) return false;

    // 查找监测点对象
    const pointObject = this.findPointObject(pointName);
    if (pointObject) {
      this.focusOnObject(pointObject);
      return true;
    }

    // 如果找不到对象，使用坐标定位
    const point = this.monitoringPoints.value.find(
      (p) => p.point_name === pointName
    );
    if (!point) return false;

    const adjustedX = (point.x - this.COORDINATE_OFFSET.x) * this.scaleFactor;
    const adjustedY = (point.y - this.COORDINATE_OFFSET.y) * this.scaleFactor;
    const adjustedZ = point.z * this.scaleFactor;

    const center = new THREE.Vector3(adjustedX, adjustedY, adjustedZ);

    // 使用更小的距离 - 与 focusOnObject 保持一致
    const distance = 200; // 从500减小到200

    const direction = new THREE.Vector3();
    this.camera.getWorldDirection(direction);

    this.camera.position.copy(center);
    this.camera.position.addScaledVector(direction, -distance);

    this.controls.target.copy(center);
    this.controls.update();

    return true;
  }
  // 辅助方法：通过名称查找点对象
  private findPointObject(pointName: string): THREE.Object3D | null {
    if (!this.scene) return null;

    let foundObject: THREE.Object3D | null = null;
    this.scene.traverse((child) => {
      if (child.name === `point_${pointName}`) {
        foundObject = child;
      }
    });

    return foundObject;
  }

  // 获取选择类型的标签样式
  public getSelectionTagType(type: string): string {
    switch (type) {
      case "point":
        return "success";
      case "shield":
        return "warning";
      case "model":
        return "primary";
      default:
        return "info";
    }
  }

  // 获取选择类型文本
  public getSelectionTypeText(type: string): string {
    switch (type) {
      case "point":
        return "监测点";
      case "shield":
        return "屏蔽区";
      case "model":
        return "模型";
      default:
        return "未知";
    }
  }

  // 获取选中的监测点ID（用于打开数据对话框）
  public getSelectedPointId(): number | null {
    if (
      !this.selectedObject.value ||
      this.selectedObject.value.type !== "point"
    )
      return null;

    const pointName = this.selectedObject.value.name;
    const point = this.monitoringPoints.value.find(
      (p) => p.point_name === pointName
    );

    return point?.point_id || null;
  }

  // 获取选中的监测点名称
public getSelectedPointName(): string | null {
  if (!this.selectedObject.value || this.selectedObject.value.type !== 'point') {
    return null;
  }
  
  return this.selectedObject.value.name;
}

  public getSelectedObjectInfo(): SelectableObject | null {
    return this.selectedObject.value;
  }

  public getSelectedShieldAreaId(): string | null {
    if (
      !this.selectedObject.value ||
      this.selectedObject.value.type !== "shield"
    ) {
      return null;
    }
    return this.selectedObject.value.id.replace("shield_", "");
  }

  // 处理画布右键点击事件
  private handleCanvasRightClick(event: MouseEvent): void {
    event.preventDefault();
    event.stopPropagation();

    console.log("SelectionManager: 画布右键点击");

    if (!this.camera || !this.scene) return;

    const canvasElement = this.renderer?.domElement;
    if (!canvasElement) return;

    const mouse = new THREE.Vector2();
    const rect = canvasElement.getBoundingClientRect();

    // 计算标准化设备坐标
    mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
    mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;

    // 执行射线检测
    this.performRaycastForContextMenu(mouse, event);
  }

  // 专门为右键菜单执行的射线检测
  // 专门为右键菜单执行的射线检测
  private performRaycastForContextMenu(
    mouse: THREE.Vector2,
    event: MouseEvent
  ): void {
    if (!this.camera || !this.scene) return;

    const raycaster = new THREE.Raycaster();
    raycaster.setFromCamera(mouse, this.camera);

    // 收集所有可选择的物体
    const selectableObjects: THREE.Object3D[] = [];

    this.scene.traverse((child) => {
      if (this.isSelectable(child)) {
        selectableObjects.push(child);
      }
    });

    const intersects = raycaster.intersectObjects(selectableObjects);

    if (intersects.length > 0) {
      const firstIntersect = intersects[0];
      console.log("右键点击选中对象:", firstIntersect.object.name);

      // 处理对象选择
      this.handleObjectSelect(firstIntersect.object);

      // 触发右键菜单事件
      if (this.onContextMenu) {
        this.onContextMenu(event, this.selectedObject.value);
      }
    } else {
      console.log("右键点击未选中任何对象");
      this.clearSelection();

      // 如果没有选中对象，也触发事件（可以用于显示全局菜单）
      if (this.onContextMenu) {
        this.onContextMenu(event, null);
      }
    }
  }
  

  // 添加右键菜单回调
  public onContextMenu:
    | ((event: MouseEvent, object: SelectableObject | null) => void)
    | null = null;

  // 清理资源
  public dispose(): void {
    const canvasElement = this.renderer?.domElement;
    if (canvasElement) {
      canvasElement.removeEventListener(
        "click",
        this.handleCanvasClick.bind(this)
      );
    }
    this.clearSelection();
  }
}
